package com.example.spring.activemq.jms.mq;

import com.example.spring.activemq.jms.constant.QueueConstant;
import com.example.spring.activemq.jms.utils.FastJsonUtils;
import com.example.spring.activemq.jms.vo.MQRstData;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;


/**
 * 监听mq，读取数据
 */
@Slf4j
@Component
public class StatusSyncReceiver {

    /**
     * //如果有消息过来，在消费的时候调用这个方法
     * //配置监听的哪一个队列，同时在没有queue和exchange的情况下会去创建并建立绑定关系
     *
     * @param channel
     * @param json
     * @param headers
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = QueueConstant.STATUSSYNC_QUEUE, durable = QueueConstant.DURABLE),
            exchange = @Exchange(name = QueueConstant.STATUSSYNC_EXCHANGE, type = QueueConstant.TYPE),
            key = QueueConstant.STATUSSYNC_KEY)
    )
    @RabbitHandler
    public void receiveObjectDel(Channel channel, String json, @Headers Map<String, Object> headers) {

        log.debug("[读取mq子订单更新状态记录 Start]");
        log.debug("[入参：{}]", json);

        /**
         * Delivery Tag 用来标识信道中投递的消息。RabbitMQ 推送消息给 Consumer 时，会附带一个 Delivery Tag，
         * 以便 Consumer 可以在消息确认时告诉 RabbitMQ 到底是哪条消息被确认了。
         * RabbitMQ 保证在每个信道中，每条消息的 Delivery Tag 从 1 开始递增。
         */
        Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);

        //手动ACK
        //默认情况下如果一个消息被消费者所正确接收则会被从队列中移除
        //如果一个队列没被任何消费者订阅，那么这个队列中的消息会被 Cache（缓存），
        //当有消费者订阅时则会立即发送，当消息被消费者正确接收时，就会被从队列中移除,这样以后就不会再发了
//        否则消息服务器以为这条消息没处理掉 后续还会在发，true确认所有消费者获得的消息
        try {

            MQRstData mqRstData = FastJsonUtils.jsonToBean(json, MQRstData.class);
            int type = mqRstData.getType();
            if (type == 1) {
                //订单状态同步业务
            } else {
                //退单状态同步业务
            }

            /**
             * deliveryTag: 该消息的index
             * multiple：是否批量.true:将一次性拒绝所有小于deliveryTag的消息;false表示通知 RabbitMQ 当前消息被确认.
             * requeue：被拒绝的是否重新入队列
             */
            channel.basicAck(deliveryTag, false);

            log.info("消息消费成功：messageId：{}", deliveryTag);
        } catch (Exception e) {
            e.printStackTrace();
            //丢弃这条消息
            try {
                //最后一个参数是：requeue:是否重回队列
                channel.basicNack(deliveryTag, false, true);
                //拒绝消息
                //channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
                //消息被丢失
                //channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                //消息被重新发送
                //channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
                //多条消息被重新发送
                //channel.basicNack(message.getMessageProperties().getDeliveryTag(), true, true);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            log.info("消息消费失败：id：{}", deliveryTag);
        }
    }

}
